#include "mboard.h"
#include "mboard_private.h"
#include "fsmc_hw.h"
#include "gpio_hw.h"
#include "dma_hw.h"
#include "rcc.h"
#include "nvic.h"
#include "mdebug.h"
#include <string.h>

/**
 * FSMC:
 *   1、引脚 
 *      PD0 --- D2
 *      PD1 --- D3
 *      PD4 --- NOE
 *      PD5 --- NWE
 *      PD8 --- D13
 *      PD9 --- D14
 *      PD10 -- D15
 *      PD11 -- A16
 *      PD12 -- A17
 *      PD13 -- A18
 *      PD14 -- D0
 *      PD15 -- D1
 *      PE0 --- NBL0
 *      PE1 --- NBL1
 *      PE7 --- D4
 *      PE8 --- D5
 *      PE9 --- D6
 *      PE10 -- D7
 *      PE11 -- D8
 *      PE12 -- D9
 *      PE13 -- D10
 *      PE14 -- D11
 *      PE15 -- D12
 *      PF0 --- A0
 *      PF1 --- A1
 *      PF2 --- A2
 *      PF3 --- A3
 *      PF4 --- A4
 *      PF5 --- A5
 *      PF12 -- A6
 *      PF13 -- A7
 *      PF14 -- A8
 *      PF15 -- A9
 *      PG0 --- A10
 *      PG1 --- A11
 *      PG2 --- A12
 *      PG3 --- A13
 *      PG4 --- A14
 *      PG5 --- A15
 *      PG10 -- NE3 -- 板子10K上拉
 *      PG12 -- NE4
 *   2、SRAM的信号线
 *      A[18:0] -- 地址总线 ----- 输出 -- 512K*16Bits=1MB
 *      D[16:0] -- 数据总线 ----- 双向 -- 16Bits
 *      NEx ------ 片选 --------- 输出 -- 低电平有效，NE3用于SRAM，NE4用于LCD
 *      NOE ------ 输出使能 ----- 输出 -- 读数据低电平，写数据高电平
 *      NWE ------ 写入使能 ----- 输出 -- 读数据高电平，写数据期间当数据从FSMC发出时拉低，然后拉高，至少1HCLK之后结束事务
 *      NBL[1:0] - 高低字节使能 - 输出 -- 写的时候使用，读的时候全0
 *   3、SRAM事务
 *      1、信号通过内部时钟 HCLK 进行同步。不会将此时钟发送到存储器
 *      2、当EXTMOD=0（禁用扩展模式）时，读写采用1套参数，MTYP=0（SRAM/NOR）/1(PSARM)时为模式1，MTYP=2（NOR/NAND）时为模式2
 *      3、当EXTMOD=1时，读写采用2套参数，模式A(SRAM/PASRM OE切换)、模式B(NOR)、模式C(NOR OE切换)、模式D(扩展地址异步访问)
 *
 * IS62WV51216 -- SRAM，16b*512=1MB，2.5-3.6V，44PIN TSOP(55ns)，还有一种BGA封装的是45ns的
 *   1、/CS=1表示未选中，所有引脚为高阻态
 *   2、/CS=0,/WE=1(表示写禁止),/OE=1(表示输出禁止)，所有引脚为高阻态
 *   3、/CS=0,/WE=1,/OE=0,/LB=1（表示低字节禁止）,/UB=0(表示高字节读取)，D[7:0]为高阻态，D[15:8]为输出
 *   4、/CS=0,/WE=0,/LB=1（表示低字节禁止）,/UB=0(表示高字节写入)，D[7:0]为高阻态，D[15:8]为输入
 */

static void mFsmcClockInit(void)
{
	/* 使能FSMC时钟 */
	RCC_EnableAhb1(RCC_CLK_AHB1_GPIOD | RCC_CLK_AHB1_GPIOE |
	               RCC_CLK_AHB1_GPIOF | RCC_CLK_AHB1_GPIOG);
	RCC_EnableAhb3(RCC_CLK_AHB3_FSMC);
}

static void mFsmcGpioInit(void)
{
	uint32_t tmp32;

	/* 复用模式 */
	tmp32 = SOC_GPIOD.MODER;
	tmp32 &= ~GPIO_MODER_MASK(0 );
	tmp32 &= ~GPIO_MODER_MASK(1 );
	tmp32 &= ~GPIO_MODER_MASK(4 );
	tmp32 &= ~GPIO_MODER_MASK(5 );
	tmp32 &= ~GPIO_MODER_MASK(8 );
	tmp32 &= ~GPIO_MODER_MASK(9 );
	tmp32 &= ~GPIO_MODER_MASK(10);
	tmp32 &= ~GPIO_MODER_MASK(11);
	tmp32 &= ~GPIO_MODER_MASK(12);
	tmp32 &= ~GPIO_MODER_MASK(13);
	tmp32 &= ~GPIO_MODER_MASK(14);
	tmp32 &= ~GPIO_MODER_MASK(15);
	tmp32 |= GPIO_MODER_AF(0 );
	tmp32 |= GPIO_MODER_AF(1 );
	tmp32 |= GPIO_MODER_AF(4 );
	tmp32 |= GPIO_MODER_AF(5 );
	tmp32 |= GPIO_MODER_AF(8 );
	tmp32 |= GPIO_MODER_AF(9 );
	tmp32 |= GPIO_MODER_AF(10);
	tmp32 |= GPIO_MODER_AF(11);
	tmp32 |= GPIO_MODER_AF(12);
	tmp32 |= GPIO_MODER_AF(13);
	tmp32 |= GPIO_MODER_AF(14);
	tmp32 |= GPIO_MODER_AF(15);
	SOC_GPIOD.MODER = tmp32;

	/* 推挽输出 */
	tmp32 = SOC_GPIOD.OTYPER;
	tmp32 &= ~GPIO_OTYPER_MASK(0 );
	tmp32 &= ~GPIO_OTYPER_MASK(1 );
	tmp32 &= ~GPIO_OTYPER_MASK(4 );
	tmp32 &= ~GPIO_OTYPER_MASK(5 );
	tmp32 &= ~GPIO_OTYPER_MASK(8 );
	tmp32 &= ~GPIO_OTYPER_MASK(9 );
	tmp32 &= ~GPIO_OTYPER_MASK(10);
	tmp32 &= ~GPIO_OTYPER_MASK(11);
	tmp32 &= ~GPIO_OTYPER_MASK(12);
	tmp32 &= ~GPIO_OTYPER_MASK(13);
	tmp32 &= ~GPIO_OTYPER_MASK(14);
	tmp32 &= ~GPIO_OTYPER_MASK(15);
	tmp32 |= GPIO_OTYPER_PP(0 );
	tmp32 |= GPIO_OTYPER_PP(1 );
	tmp32 |= GPIO_OTYPER_PP(4 );
	tmp32 |= GPIO_OTYPER_PP(5 );
	tmp32 |= GPIO_OTYPER_PP(8 );
	tmp32 |= GPIO_OTYPER_PP(9 );
	tmp32 |= GPIO_OTYPER_PP(10);
	tmp32 |= GPIO_OTYPER_PP(11);
	tmp32 |= GPIO_OTYPER_PP(12);
	tmp32 |= GPIO_OTYPER_PP(13);
	tmp32 |= GPIO_OTYPER_PP(14);
	tmp32 |= GPIO_OTYPER_PP(15);
	SOC_GPIOD.OTYPER = tmp32;

	/* 100M的输出速度 */
	tmp32 = SOC_GPIOD.OSPEEDR;
	tmp32 &= ~GPIO_OSPEEDR_MASK(0 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(1 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(4 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(5 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(8 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(9 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(10);
	tmp32 &= ~GPIO_OSPEEDR_MASK(11);
	tmp32 &= ~GPIO_OSPEEDR_MASK(12);
	tmp32 &= ~GPIO_OSPEEDR_MASK(13);
	tmp32 &= ~GPIO_OSPEEDR_MASK(14);
	tmp32 &= ~GPIO_OSPEEDR_MASK(15);
	tmp32 |= GPIO_OSPEEDR_100M(0 );
	tmp32 |= GPIO_OSPEEDR_100M(1 );
	tmp32 |= GPIO_OSPEEDR_100M(4 );
	tmp32 |= GPIO_OSPEEDR_100M(5 );
	tmp32 |= GPIO_OSPEEDR_100M(8 );
	tmp32 |= GPIO_OSPEEDR_100M(9 );
	tmp32 |= GPIO_OSPEEDR_100M(10);
	tmp32 |= GPIO_OSPEEDR_100M(11);
	tmp32 |= GPIO_OSPEEDR_100M(12);
	tmp32 |= GPIO_OSPEEDR_100M(13);
	tmp32 |= GPIO_OSPEEDR_100M(14);
	tmp32 |= GPIO_OSPEEDR_100M(15);
	SOC_GPIOD.OSPEEDR = tmp32;

	/* 禁用上下拉 */
	tmp32 = SOC_GPIOD.PUPDR;
	tmp32 &= ~GPIO_PUPDR_MASK(0 );
	tmp32 &= ~GPIO_PUPDR_MASK(1 );
	tmp32 &= ~GPIO_PUPDR_MASK(4 );
	tmp32 &= ~GPIO_PUPDR_MASK(5 );
	tmp32 &= ~GPIO_PUPDR_MASK(8 );
	tmp32 &= ~GPIO_PUPDR_MASK(9 );
	tmp32 &= ~GPIO_PUPDR_MASK(10);
	tmp32 &= ~GPIO_PUPDR_MASK(11);
	tmp32 &= ~GPIO_PUPDR_MASK(12);
	tmp32 &= ~GPIO_PUPDR_MASK(13);
	tmp32 &= ~GPIO_PUPDR_MASK(14);
	tmp32 &= ~GPIO_PUPDR_MASK(15);
	tmp32 |= GPIO_PUPDR_NONE(0 );
	tmp32 |= GPIO_PUPDR_NONE(1 );
	tmp32 |= GPIO_PUPDR_NONE(4 );
	tmp32 |= GPIO_PUPDR_NONE(5 );
	tmp32 |= GPIO_PUPDR_NONE(8 );
	tmp32 |= GPIO_PUPDR_NONE(9 );
	tmp32 |= GPIO_PUPDR_NONE(10);
	tmp32 |= GPIO_PUPDR_NONE(11);
	tmp32 |= GPIO_PUPDR_NONE(12);
	tmp32 |= GPIO_PUPDR_NONE(13);
	tmp32 |= GPIO_PUPDR_NONE(14);
	tmp32 |= GPIO_PUPDR_NONE(15);
	SOC_GPIOD.PUPDR = tmp32;

	/* IO复用为FSMC */
	tmp32 = SOC_GPIOD.AFLR;
	tmp32 &= ~GPIO_AFLR_MASK(0 );
	tmp32 &= ~GPIO_AFLR_MASK(1 );
	tmp32 &= ~GPIO_AFLR_MASK(4 );
	tmp32 &= ~GPIO_AFLR_MASK(5 );
	tmp32 |= GPIO_AFLR_0_15D(0 , 12);
	tmp32 |= GPIO_AFLR_0_15D(1 , 12);
	tmp32 |= GPIO_AFLR_0_15D(4 , 12);
	tmp32 |= GPIO_AFLR_0_15D(5 , 12);
	SOC_GPIOD.AFLR = tmp32;

	tmp32 = SOC_GPIOD.AFHR;
	tmp32 &= ~GPIO_AFHR_MASK(8 );
	tmp32 &= ~GPIO_AFHR_MASK(9 );
	tmp32 &= ~GPIO_AFHR_MASK(10);
	tmp32 &= ~GPIO_AFHR_MASK(11);
	tmp32 &= ~GPIO_AFHR_MASK(12);
	tmp32 &= ~GPIO_AFHR_MASK(13);
	tmp32 &= ~GPIO_AFHR_MASK(14);
	tmp32 &= ~GPIO_AFHR_MASK(15);
	tmp32 |= GPIO_AFHR_0_15D(8 , 12);
	tmp32 |= GPIO_AFHR_0_15D(9 , 12);
	tmp32 |= GPIO_AFHR_0_15D(10, 12);
	tmp32 |= GPIO_AFHR_0_15D(11, 12);
	tmp32 |= GPIO_AFHR_0_15D(12, 12);
	tmp32 |= GPIO_AFHR_0_15D(13, 12);
	tmp32 |= GPIO_AFHR_0_15D(14, 12);
	tmp32 |= GPIO_AFHR_0_15D(15, 12);
	SOC_GPIOD.AFHR = tmp32;

	/* 复用模式 */
	tmp32 = SOC_GPIOE.MODER;
	tmp32 &= ~GPIO_MODER_MASK(0 );
	tmp32 &= ~GPIO_MODER_MASK(1 );
	tmp32 &= ~GPIO_MODER_MASK(7 );
	tmp32 &= ~GPIO_MODER_MASK(8 );
	tmp32 &= ~GPIO_MODER_MASK(9 );
	tmp32 &= ~GPIO_MODER_MASK(10);
	tmp32 &= ~GPIO_MODER_MASK(11);
	tmp32 &= ~GPIO_MODER_MASK(12);
	tmp32 &= ~GPIO_MODER_MASK(13);
	tmp32 &= ~GPIO_MODER_MASK(14);
	tmp32 &= ~GPIO_MODER_MASK(15);
	tmp32 |= GPIO_MODER_AF(0 );
	tmp32 |= GPIO_MODER_AF(1 );
	tmp32 |= GPIO_MODER_AF(7 );
	tmp32 |= GPIO_MODER_AF(8 );
	tmp32 |= GPIO_MODER_AF(9 );
	tmp32 |= GPIO_MODER_AF(10);
	tmp32 |= GPIO_MODER_AF(11);
	tmp32 |= GPIO_MODER_AF(12);
	tmp32 |= GPIO_MODER_AF(13);
	tmp32 |= GPIO_MODER_AF(14);
	tmp32 |= GPIO_MODER_AF(15);
	SOC_GPIOE.MODER = tmp32;

	/* 推挽输出 */
	tmp32 = SOC_GPIOE.OTYPER;
	tmp32 &= ~GPIO_OTYPER_MASK(0 );
	tmp32 &= ~GPIO_OTYPER_MASK(1 );
	tmp32 &= ~GPIO_OTYPER_MASK(7 );
	tmp32 &= ~GPIO_OTYPER_MASK(8 );
	tmp32 &= ~GPIO_OTYPER_MASK(9 );
	tmp32 &= ~GPIO_OTYPER_MASK(10);
	tmp32 &= ~GPIO_OTYPER_MASK(11);
	tmp32 &= ~GPIO_OTYPER_MASK(12);
	tmp32 &= ~GPIO_OTYPER_MASK(13);
	tmp32 &= ~GPIO_OTYPER_MASK(14);
	tmp32 &= ~GPIO_OTYPER_MASK(15);
	tmp32 |= GPIO_OTYPER_PP(0 );
	tmp32 |= GPIO_OTYPER_PP(1 );
	tmp32 |= GPIO_OTYPER_PP(7 );
	tmp32 |= GPIO_OTYPER_PP(8 );
	tmp32 |= GPIO_OTYPER_PP(9 );
	tmp32 |= GPIO_OTYPER_PP(10);
	tmp32 |= GPIO_OTYPER_PP(11);
	tmp32 |= GPIO_OTYPER_PP(12);
	tmp32 |= GPIO_OTYPER_PP(13);
	tmp32 |= GPIO_OTYPER_PP(14);
	tmp32 |= GPIO_OTYPER_PP(15);
	SOC_GPIOE.OTYPER = tmp32;

	/* 100M的输出速度 */
	tmp32 = SOC_GPIOE.OSPEEDR;
	tmp32 &= ~GPIO_OSPEEDR_MASK(0 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(1 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(7 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(8 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(9 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(10);
	tmp32 &= ~GPIO_OSPEEDR_MASK(11);
	tmp32 &= ~GPIO_OSPEEDR_MASK(12);
	tmp32 &= ~GPIO_OSPEEDR_MASK(13);
	tmp32 &= ~GPIO_OSPEEDR_MASK(14);
	tmp32 &= ~GPIO_OSPEEDR_MASK(15);
	tmp32 |= GPIO_OSPEEDR_100M(0 );
	tmp32 |= GPIO_OSPEEDR_100M(1 );
	tmp32 |= GPIO_OSPEEDR_100M(7 );
	tmp32 |= GPIO_OSPEEDR_100M(8 );
	tmp32 |= GPIO_OSPEEDR_100M(9 );
	tmp32 |= GPIO_OSPEEDR_100M(10);
	tmp32 |= GPIO_OSPEEDR_100M(11);
	tmp32 |= GPIO_OSPEEDR_100M(12);
	tmp32 |= GPIO_OSPEEDR_100M(13);
	tmp32 |= GPIO_OSPEEDR_100M(14);
	tmp32 |= GPIO_OSPEEDR_100M(15);
	SOC_GPIOE.OSPEEDR = tmp32;

	/* 禁用上下拉 */
	tmp32 = SOC_GPIOE.PUPDR;
	tmp32 &= ~GPIO_PUPDR_MASK(0 );
	tmp32 &= ~GPIO_PUPDR_MASK(1 );
	tmp32 &= ~GPIO_PUPDR_MASK(7 );
	tmp32 &= ~GPIO_PUPDR_MASK(8 );
	tmp32 &= ~GPIO_PUPDR_MASK(9 );
	tmp32 &= ~GPIO_PUPDR_MASK(10);
	tmp32 &= ~GPIO_PUPDR_MASK(11);
	tmp32 &= ~GPIO_PUPDR_MASK(12);
	tmp32 &= ~GPIO_PUPDR_MASK(13);
	tmp32 &= ~GPIO_PUPDR_MASK(14);
	tmp32 &= ~GPIO_PUPDR_MASK(15);
	tmp32 |= GPIO_PUPDR_NONE(0 );
	tmp32 |= GPIO_PUPDR_NONE(1 );
	tmp32 |= GPIO_PUPDR_NONE(7 );
	tmp32 |= GPIO_PUPDR_NONE(8 );
	tmp32 |= GPIO_PUPDR_NONE(9 );
	tmp32 |= GPIO_PUPDR_NONE(10);
	tmp32 |= GPIO_PUPDR_NONE(11);
	tmp32 |= GPIO_PUPDR_NONE(12);
	tmp32 |= GPIO_PUPDR_NONE(13);
	tmp32 |= GPIO_PUPDR_NONE(14);
	tmp32 |= GPIO_PUPDR_NONE(15);
	SOC_GPIOE.PUPDR = tmp32;

	/* IO复用为FSMC */
	tmp32 = SOC_GPIOE.AFLR;
	tmp32 &= ~GPIO_AFLR_MASK(0 );
	tmp32 &= ~GPIO_AFLR_MASK(1 );
	tmp32 &= ~GPIO_AFLR_MASK(7 );
	tmp32 |= GPIO_AFLR_0_15D(0 , 12);
	tmp32 |= GPIO_AFLR_0_15D(1 , 12);
	tmp32 |= GPIO_AFLR_0_15D(5 , 12);
	tmp32 |= GPIO_AFLR_0_15D(6 , 12);
	tmp32 |= GPIO_AFLR_0_15D(7 , 12);
	SOC_GPIOE.AFLR = tmp32;

	tmp32 = SOC_GPIOE.AFHR;
	tmp32 &= ~GPIO_AFHR_MASK(8 );
	tmp32 &= ~GPIO_AFHR_MASK(9 );
	tmp32 &= ~GPIO_AFHR_MASK(10);
	tmp32 &= ~GPIO_AFHR_MASK(11);
	tmp32 &= ~GPIO_AFHR_MASK(12);
	tmp32 &= ~GPIO_AFHR_MASK(13);
	tmp32 &= ~GPIO_AFHR_MASK(14);
	tmp32 &= ~GPIO_AFHR_MASK(15);
	tmp32 |= GPIO_AFHR_0_15D(8 , 12);
	tmp32 |= GPIO_AFHR_0_15D(9 , 12);
	tmp32 |= GPIO_AFHR_0_15D(10, 12);
	tmp32 |= GPIO_AFHR_0_15D(11, 12);
	tmp32 |= GPIO_AFHR_0_15D(12, 12);
	tmp32 |= GPIO_AFHR_0_15D(13, 12);
	tmp32 |= GPIO_AFHR_0_15D(14, 12);
	tmp32 |= GPIO_AFHR_0_15D(15, 12);
	SOC_GPIOE.AFHR = tmp32;

	/* 复用模式 */
	tmp32 = SOC_GPIOF.MODER;
	tmp32 &= ~GPIO_MODER_MASK(0 );
	tmp32 &= ~GPIO_MODER_MASK(1 );
	tmp32 &= ~GPIO_MODER_MASK(2 );
	tmp32 &= ~GPIO_MODER_MASK(3 );
	tmp32 &= ~GPIO_MODER_MASK(4 );
	tmp32 &= ~GPIO_MODER_MASK(5 );
	tmp32 &= ~GPIO_MODER_MASK(12);
	tmp32 &= ~GPIO_MODER_MASK(13);
	tmp32 &= ~GPIO_MODER_MASK(14);
	tmp32 &= ~GPIO_MODER_MASK(15);
	tmp32 |= GPIO_MODER_AF(0 );
	tmp32 |= GPIO_MODER_AF(1 );
	tmp32 |= GPIO_MODER_AF(2 );
	tmp32 |= GPIO_MODER_AF(3 );
	tmp32 |= GPIO_MODER_AF(4 );
	tmp32 |= GPIO_MODER_AF(5 );
	tmp32 |= GPIO_MODER_AF(12);
	tmp32 |= GPIO_MODER_AF(13);
	tmp32 |= GPIO_MODER_AF(14);
	tmp32 |= GPIO_MODER_AF(15);
	SOC_GPIOF.MODER = tmp32;

	/* 推挽输出 */
	tmp32 = SOC_GPIOF.OTYPER;
	tmp32 &= ~GPIO_OTYPER_MASK(0 );
	tmp32 &= ~GPIO_OTYPER_MASK(1 );
	tmp32 &= ~GPIO_OTYPER_MASK(2 );
	tmp32 &= ~GPIO_OTYPER_MASK(3 );
	tmp32 &= ~GPIO_OTYPER_MASK(4 );
	tmp32 &= ~GPIO_OTYPER_MASK(5 );
	tmp32 &= ~GPIO_OTYPER_MASK(12);
	tmp32 &= ~GPIO_OTYPER_MASK(13);
	tmp32 &= ~GPIO_OTYPER_MASK(14);
	tmp32 &= ~GPIO_OTYPER_MASK(15);
	tmp32 |= GPIO_OTYPER_PP(0 );
	tmp32 |= GPIO_OTYPER_PP(1 );
	tmp32 |= GPIO_OTYPER_PP(2 );
	tmp32 |= GPIO_OTYPER_PP(3 );
	tmp32 |= GPIO_OTYPER_PP(4 );
	tmp32 |= GPIO_OTYPER_PP(5 );
	tmp32 |= GPIO_OTYPER_PP(12);
	tmp32 |= GPIO_OTYPER_PP(13);
	tmp32 |= GPIO_OTYPER_PP(14);
	tmp32 |= GPIO_OTYPER_PP(15);
	SOC_GPIOF.OTYPER = tmp32;

	/* 100M的输出速度 */
	tmp32 = SOC_GPIOF.OSPEEDR;
	tmp32 &= ~GPIO_OSPEEDR_MASK(0 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(1 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(2 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(3 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(4 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(5 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(12);
	tmp32 &= ~GPIO_OSPEEDR_MASK(13);
	tmp32 &= ~GPIO_OSPEEDR_MASK(14);
	tmp32 &= ~GPIO_OSPEEDR_MASK(15);
	tmp32 |= GPIO_OSPEEDR_100M(0 );
	tmp32 |= GPIO_OSPEEDR_100M(1 );
	tmp32 |= GPIO_OSPEEDR_100M(2 );
	tmp32 |= GPIO_OSPEEDR_100M(3 );
	tmp32 |= GPIO_OSPEEDR_100M(4 );
	tmp32 |= GPIO_OSPEEDR_100M(5 );
	tmp32 |= GPIO_OSPEEDR_100M(12);
	tmp32 |= GPIO_OSPEEDR_100M(13);
	tmp32 |= GPIO_OSPEEDR_100M(14);
	tmp32 |= GPIO_OSPEEDR_100M(15);
	SOC_GPIOF.OSPEEDR = tmp32;

	/* 禁用上下拉 */
	tmp32 = SOC_GPIOF.PUPDR;
	tmp32 &= ~GPIO_PUPDR_MASK(0 );
	tmp32 &= ~GPIO_PUPDR_MASK(1 );
	tmp32 &= ~GPIO_PUPDR_MASK(2 );
	tmp32 &= ~GPIO_PUPDR_MASK(3 );
	tmp32 &= ~GPIO_PUPDR_MASK(4 );
	tmp32 &= ~GPIO_PUPDR_MASK(5 );
	tmp32 &= ~GPIO_PUPDR_MASK(12);
	tmp32 &= ~GPIO_PUPDR_MASK(13);
	tmp32 &= ~GPIO_PUPDR_MASK(14);
	tmp32 &= ~GPIO_PUPDR_MASK(15);
	tmp32 |= GPIO_PUPDR_NONE(0 );
	tmp32 |= GPIO_PUPDR_NONE(1 );
	tmp32 |= GPIO_PUPDR_NONE(2 );
	tmp32 |= GPIO_PUPDR_NONE(3 );
	tmp32 |= GPIO_PUPDR_NONE(4 );
	tmp32 |= GPIO_PUPDR_NONE(5 );
	tmp32 |= GPIO_PUPDR_NONE(12);
	tmp32 |= GPIO_PUPDR_NONE(13);
	tmp32 |= GPIO_PUPDR_NONE(14);
	tmp32 |= GPIO_PUPDR_NONE(15);
	SOC_GPIOF.PUPDR = tmp32;

	/* IO复用为FSMC */
	tmp32 = SOC_GPIOF.AFLR;
	tmp32 &= ~GPIO_AFLR_MASK(0 );
	tmp32 &= ~GPIO_AFLR_MASK(1 );
	tmp32 &= ~GPIO_AFLR_MASK(2 );
	tmp32 &= ~GPIO_AFLR_MASK(3 );
	tmp32 &= ~GPIO_AFLR_MASK(4 );
	tmp32 &= ~GPIO_AFLR_MASK(5 );
	tmp32 |= GPIO_AFLR_0_15D(0 , 12);
	tmp32 |= GPIO_AFLR_0_15D(1 , 12);
	tmp32 |= GPIO_AFLR_0_15D(2 , 12);
	tmp32 |= GPIO_AFLR_0_15D(3 , 12);
	tmp32 |= GPIO_AFLR_0_15D(4 , 12);
	tmp32 |= GPIO_AFLR_0_15D(5 , 12);
	SOC_GPIOF.AFLR = tmp32;

	tmp32 = SOC_GPIOF.AFHR;
	tmp32 &= ~GPIO_AFHR_MASK(12);
	tmp32 &= ~GPIO_AFHR_MASK(13);
	tmp32 &= ~GPIO_AFHR_MASK(14);
	tmp32 &= ~GPIO_AFHR_MASK(15);
	tmp32 |= GPIO_AFHR_0_15D(12, 12);
	tmp32 |= GPIO_AFHR_0_15D(13, 12);
	tmp32 |= GPIO_AFHR_0_15D(14, 12);
	tmp32 |= GPIO_AFHR_0_15D(15, 12);
	SOC_GPIOF.AFHR = tmp32;

	/* 复用模式 */
	tmp32 = SOC_GPIOG.MODER;
	tmp32 &= ~GPIO_MODER_MASK(0 );
	tmp32 &= ~GPIO_MODER_MASK(1 );
	tmp32 &= ~GPIO_MODER_MASK(2 );
	tmp32 &= ~GPIO_MODER_MASK(3 );
	tmp32 &= ~GPIO_MODER_MASK(4 );
	tmp32 &= ~GPIO_MODER_MASK(5 );
	tmp32 &= ~GPIO_MODER_MASK(10);
	tmp32 &= ~GPIO_MODER_MASK(12);
	tmp32 |= GPIO_MODER_AF(0 );
	tmp32 |= GPIO_MODER_AF(1 );
	tmp32 |= GPIO_MODER_AF(2 );
	tmp32 |= GPIO_MODER_AF(3 );
	tmp32 |= GPIO_MODER_AF(4 );
	tmp32 |= GPIO_MODER_AF(5 );
	tmp32 |= GPIO_MODER_AF(10);
	tmp32 |= GPIO_MODER_AF(12);
	SOC_GPIOG.MODER = tmp32;

	/* 推挽输出 */
	tmp32 = SOC_GPIOG.OTYPER;
	tmp32 &= ~GPIO_OTYPER_MASK(0 );
	tmp32 &= ~GPIO_OTYPER_MASK(1 );
	tmp32 &= ~GPIO_OTYPER_MASK(2 );
	tmp32 &= ~GPIO_OTYPER_MASK(3 );
	tmp32 &= ~GPIO_OTYPER_MASK(4 );
	tmp32 &= ~GPIO_OTYPER_MASK(5 );
	tmp32 &= ~GPIO_OTYPER_MASK(10);
	tmp32 &= ~GPIO_OTYPER_MASK(12);
	tmp32 |= GPIO_OTYPER_PP(0 );
	tmp32 |= GPIO_OTYPER_PP(1 );
	tmp32 |= GPIO_OTYPER_PP(2 );
	tmp32 |= GPIO_OTYPER_PP(3 );
	tmp32 |= GPIO_OTYPER_PP(4 );
	tmp32 |= GPIO_OTYPER_PP(5 );
	tmp32 |= GPIO_OTYPER_PP(10);
	tmp32 |= GPIO_OTYPER_PP(12);
	SOC_GPIOG.OTYPER = tmp32;

	/* 100M的输出速度 */
	tmp32 = SOC_GPIOG.OSPEEDR;
	tmp32 &= ~GPIO_OSPEEDR_MASK(0 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(1 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(2 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(3 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(4 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(5 );
	tmp32 &= ~GPIO_OSPEEDR_MASK(10);
	tmp32 &= ~GPIO_OSPEEDR_MASK(12);
	tmp32 |= GPIO_OSPEEDR_100M(0 );
	tmp32 |= GPIO_OSPEEDR_100M(1 );
	tmp32 |= GPIO_OSPEEDR_100M(2 );
	tmp32 |= GPIO_OSPEEDR_100M(3 );
	tmp32 |= GPIO_OSPEEDR_100M(4 );
	tmp32 |= GPIO_OSPEEDR_100M(5 );
	tmp32 |= GPIO_OSPEEDR_100M(10);
	tmp32 |= GPIO_OSPEEDR_100M(12);
	SOC_GPIOG.OSPEEDR = tmp32;

	/* 禁用上下拉 */
	tmp32 = SOC_GPIOG.PUPDR;
	tmp32 &= ~GPIO_PUPDR_MASK(0 );
	tmp32 &= ~GPIO_PUPDR_MASK(1 );
	tmp32 &= ~GPIO_PUPDR_MASK(2 );
	tmp32 &= ~GPIO_PUPDR_MASK(3 );
	tmp32 &= ~GPIO_PUPDR_MASK(4 );
	tmp32 &= ~GPIO_PUPDR_MASK(5 );
	tmp32 &= ~GPIO_PUPDR_MASK(10);
	tmp32 &= ~GPIO_PUPDR_MASK(12);
	tmp32 |= GPIO_PUPDR_NONE(0 );
	tmp32 |= GPIO_PUPDR_NONE(1 );
	tmp32 |= GPIO_PUPDR_NONE(2 );
	tmp32 |= GPIO_PUPDR_NONE(3 );
	tmp32 |= GPIO_PUPDR_NONE(4 );
	tmp32 |= GPIO_PUPDR_NONE(5 );
	tmp32 |= GPIO_PUPDR_NONE(10);
	tmp32 |= GPIO_PUPDR_NONE(12);
	SOC_GPIOG.PUPDR = tmp32;

	/* IO复用为FSMC */
	tmp32 = SOC_GPIOG.AFLR;
	tmp32 &= ~GPIO_AFLR_MASK(0 );
	tmp32 &= ~GPIO_AFLR_MASK(1 );
	tmp32 &= ~GPIO_AFLR_MASK(2 );
	tmp32 &= ~GPIO_AFLR_MASK(3 );
	tmp32 &= ~GPIO_AFLR_MASK(4 );
	tmp32 &= ~GPIO_AFLR_MASK(5 );
	tmp32 |= GPIO_AFLR_0_15D(0 , 12);
	tmp32 |= GPIO_AFLR_0_15D(1 , 12);
	tmp32 |= GPIO_AFLR_0_15D(2 , 12);
	tmp32 |= GPIO_AFLR_0_15D(3 , 12);
	tmp32 |= GPIO_AFLR_0_15D(4 , 12);
	tmp32 |= GPIO_AFLR_0_15D(5 , 12);
	SOC_GPIOG.AFLR = tmp32;

	tmp32 = SOC_GPIOG.AFHR;
	tmp32 &= ~GPIO_AFHR_MASK(10);
	tmp32 &= ~GPIO_AFHR_MASK(12);
	tmp32 |= GPIO_AFHR_0_15D(10, 12);
	tmp32 |= GPIO_AFHR_0_15D(12, 12);
	SOC_GPIOG.AFHR = tmp32;
}

static void mFsmcDeviceInit(void)
{
	/* 采用模式A使用BANK1的分区3(对应NE3)，地址为0x68000000-0x68100000(1MB) */
	SOC_FSMC_B1.BCR3 = FSMC_B1_BCRx_RESERVED |      // 保留位
	                   FSMC_B1_BCRx_MBKEN_EN |      // 使能该存储区域
	                   FSMC_B1_BCRx_MUXEN_DIS |     // 地址数据总线不复用
	                   FSMC_B1_BCRx_MTYP_SRAM_ROM | // 控制类型为SRAM
	                   FSMC_B1_BCRx_MWID_16B |      // 数据位宽为16B
	                   FSMC_B1_BCRx_BURSTEN_DIS |   // 禁用突发访问
	                   FSMC_B1_BCRx_WAITPOL_LOW |   // 低电平有效，ASYNCWAIT_DIS时无意义
	                   FSMC_B1_BCRx_WRAPMOD_DIS |   // 禁用直接回环突发
	                   FSMC_B1_BCRx_WAITCFG_PREV |  // NWAIT信号生效时期，ASYNCWAIT_DIS时无意义
	                   FSMC_B1_BCRx_WREN_EN |       // 使能写入操作
	                   FSMC_B1_BCRx_WAITEN_DIS |    // 禁止 NWAIT 信号，异步操作无意义
	                   FSMC_B1_BCRx_EXTMOD_EN |     // 使能扩展模式
	                   FSMC_B1_BCRx_ASYNCWAIT_DIS | // 运行异步协议时不考虑 NWAIT 信号
	                   FSMC_B1_BCRx_CPSIZE_NONE |   // 突发访问不需要拆分，异步操作无意义
	                   FSMC_B1_BCRx_CBURSTRW_ASYNC; // 始终在异步模式下进行写入操作
	/* AHB时钟为168MHz，1/168M=5.95ns，参考IS62W手册 READ CYCLE NO. 2章节
	   ADDSET: 地址输出到NOE拉低的时间，对应IS62W手册tAA-tDOE=55-25=30ns/5.95=5=29.76ns
	   DATAST: NOE拉低到地址结束的时间，对应IS62W手册tRC-(tAA-tDOE)=25ns/5.95=5=29.76ns
	   BUSTURN: tSDR=0ns(DATA RETENTION WAVEFORM) */
	SOC_FSMC_B1.BTR3 = FSMC_B1_ByTRx_ADDSET_V_0_15D(5) |  // 地址设置阶段的持续时间，第一个访问阶段持续时间
	                   FSMC_B1_ByTRx_ADDHLD_V_1_15D(0) |  // 地址保持阶段的持续时间，无关
	                   FSMC_B1_ByTRx_DATAST_V_1_255D(5) | // 数据阶段的持续时间，第二个访问阶段持续时间
	                   FSMC_B1_ByTRx_BUSTURN_V_0_15D(0) | // 事务结束延时，NEx高电平到低电平的时间
	                   FSMC_B1_ByTRx_CLKDIV_V_2_16D(2) |  // 时钟分频，无关
	                   FSMC_B1_ByTRx_DATLAT_V_2_17D(2) |  // 首个数据前要发送给存储器的存储器时钟周期数，无关
	                   FSMC_B1_ByTRx_ACCMOD_A;            // 访问模式A
	/* BWTR和BTR的字段是一样的，参考IS62W手册 WRITE CYCLE NO.4章节
	   ADDSET: 地址输出到NWE拉低的时间，对应tSA=0ns
	   DATAST: NWE拉低到地址结束的时间，对应tWC-tSA=55ns/5.95=10=59.5ns
	   BUSTURN: tSDR=0ns(DATA RETENTION WAVEFORM) */
	SOC_FSMC_B1E.BWTR3 = FSMC_B1_ByTRx_ADDSET_V_0_15D(0) |
	                    FSMC_B1_ByTRx_ADDHLD_V_1_15D(0) |    // 无关
	                    FSMC_B1_ByTRx_DATAST_V_1_255D(5-1) | // 写的时候，硬件会多加一个周期
	                    FSMC_B1_ByTRx_BUSTURN_V_0_15D(0) |
	                    FSMC_B1_ByTRx_CLKDIV_V_2_16D(2) |    // 无关
	                    FSMC_B1_ByTRx_DATLAT_V_2_17D(2) |    // 无关
	                    FSMC_B1_ByTRx_ACCMOD_A;
}

static void mFsmcInterrupt(void)
{
}

static void mFsmcDmaInit(void)
{
}

void mFsmcInit(void)
{
	mFsmcClockInit();
	mFsmcGpioInit();
	mFsmcDeviceInit();
	mFsmcInterrupt();
	mFsmcDmaInit();
}

void mFsmcTest(void)
{
	volatile uint32_t *u32Start = (volatile uint32_t *)SOC_FSMC_SRAM_STAR;
	volatile uint32_t *u32End = (volatile uint32_t *)(SOC_FSMC_SRAM_END+1);
	volatile uint32_t *u32Addr;
	volatile uint8_t *u8Start = (volatile uint8_t *)SOC_FSMC_SRAM_STAR;
	volatile uint8_t *u8End = (volatile uint8_t *)(SOC_FSMC_SRAM_END+1);
	volatile uint8_t *u8Addr;
	uint32_t i;

	mDebugPuts("FSMC SRAM U32测试");
	for (u32Addr = u32Start; u32Addr < u32End; u32Addr += 1024) {
		for (i = 0; i < 1024; i++) {
			u32Addr[i] = i;
		}
		for (i = 0; i < 1024; i++) {
			if (u32Addr[i] != i) {
				mDebugPrintf("addr[%08x] value %08x expect %08x" MDEBUG_ENDL,
				             (uint32_t)&u32Addr[i], u32Addr[i], i);
			}
		}
	}
	mDebugPuts("FSMC SRAM U8测试");
	for (u8Addr = u8Start; u8Addr < u8End; u8Addr += 255) {
		for (i = 0; i < 255; i++) {
			u8Addr[i] = i;
		}
		for (i = 0; i < 255; i++) {
			if (u8Addr[i] != i) {
				mDebugPrintf("addr[%08x] value %02x expect %02x" MDEBUG_ENDL,
				             (uint32_t)&u8Addr[i], u8Addr[i], i);
			}
		}
	}
}
